/* 
 * Quechua - the lightweight data mining framework
 *
 * Copyright (C) 2012 Marek Denis <quechua@octogan.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef IPTRIE_H
#define IPTRIE_H

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cstring>
#include "../../../include/log.h"
#include "../../data/types.h"
#include "types.h"

static const short WIDTH = 256; /* number of combinations on 8 bits - 2**8 */
class ipIndex;
typedef std::shared_ptr<in6_addr> in6_addr_ptr;
typedef std::shared_ptr<ipIndex> ipIndex_ptr;

enum INDEX_TYPE {
  SRC = 0x1,
  DST = 0x2,
  BOTH= 0x3
};

class ipIndex {
 public:
    static int ipCounter;
    u_int8_t ver; // AF_INET or AF_INET6 from from <socket.h> headers
    INDEX_TYPE type; // DST, SRC, BOTH
    index_t src_idx;
    index_t dst_idx;
    in6_addr_ptr addr; // really necessary? 
    const char* ip;

    ipIndex();
    ~ipIndex();
    bool handle_mem(bool handle);
 private:
    bool ownmemory;
};


class IpNode {
 public:
    IpNode();
    ~IpNode();

    IpNode* set(const u_int8_t* label,u_int8_t len,
            ipIndex_ptr idx_node, bool overwrite = false);

    IpNode* get(const u_int8_t* label,u_int8_t len);
//    ipIndex* value;
    ipIndex_ptr value;
    IpNode* children[WIDTH];
};

class IpTrie {
 public:
    IpTrie(const u_int8_t height);
    ~IpTrie();

    IpNode* getNode(const u_int8_t* label,u_int8_t len); // const unsigned char*
    IpNode* setNode(const u_int8_t* label,u_int8_t len, ipIndex_ptr idx_node, bool overwrite = false); // const unsigned char*
 private:
    IpNode* root;
    const u_int8_t height; 
};

#endif /* IPTRIE_H */
